﻿using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using Slippor.Douban.Radio.Assist;
using HundredMilesSoftware.UltraID3Lib;

namespace RestoreHandlerPlugin
{
    public class IECacheFileFetcher
    {
        private String _cachePath = Environment.GetFolderPath(Environment.SpecialFolder.InternetCache);

        public FileInfo GetFile(Song song)
        {
            return GetFile(String.Format("p{0}[*].mp3", song.SongID));
        }

        public FileInfo GetFile(Album album)
        {
            return GetFile(String.Format("{0}[*].jpg", album.CoverID));
        }

        private FileInfo GetFile(String searchPattern)
        {
            DirectoryInfo dir = new DirectoryInfo(_cachePath);
            FileInfo[] files = dir.GetFiles(searchPattern, SearchOption.AllDirectories);
            if (files.Length > 0)
            {
                if (files.Length > 1)
                {
                    FileInfo info = null;
                    foreach (FileInfo file in files)
                    {
                        if (info == null || file.Length > info.Length)
                        {
                            info = file;
                        }
                    }
                }
                return files[0];
            }
            return null;
        }

        public String CopySong(Song song, String path, String nameFormate, bool onlyFull, DirOptions dirOptions)
        {
            FileInfo info = GetFile(song);
            if (info != null)
            {
                try
                {
                    using (FileStream objFileStream = new FileStream(info.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                    {
                        if (!onlyFull || CheckFull(info))
                        {
                            DirectoryInfo dir = GetDir(path, dirOptions, song.Album);
                            String fullName = info.FullName;
                            String newName = GetName(nameFormate, song);
                            String newPath = Path.Combine(dir.FullName, String.Format("{0}.mp3", newName));
                            if(File.Exists(newPath))
                            {
                                FileInfo fileInfo = new FileInfo(newPath);
                                if(fileInfo.Length > info.Length)
                                {
                                    return newPath;
                                }
                            }
                            File.Copy(fullName, newPath, true);
                            MP3Header.WriteHeader(newPath, new MP3(song));
                            return newPath;
                        }
                        else
                        {
                            Trace.TraceError(String.Format("歌曲文件不完整 {0}", song.SongID));
                            return String.Empty;
                        }
                    }
                }
                catch (Exception e)
                {
                    Trace.TraceError(e.Message);
                    return String.Empty;
                }
            }
            Trace.TraceError(String.Format("没有找到歌曲文件 {0}", song.SongID));
            return String.Empty;
        }

        public String CopyCover(Album album, String path, DirOptions dirOptions)
        {
            FileInfo info = GetFile(album);
            if (info != null)
            {
                try
                {
                    using (FileStream objFileStream = new FileStream(info.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                    {
                        DirectoryInfo dir = GetDir(path, dirOptions, album);
                        String fullName = info.FullName;
                        String newName = BuildFileableName(album.Name);
                        String newPath = Path.Combine(dir.FullName, String.Format("{0}.jpg", newName));
                        if (File.Exists(newPath))
                        {
                            FileInfo fileInfo = new FileInfo(newPath);
                            if (fileInfo.Length > info.Length)
                            {
                                return newPath;
                            }
                        }
                        File.Copy(fullName, newPath, true);
                        return newPath;
                    }
                }
                catch (Exception e)
                {
                    Trace.TraceError(e.Message);
                    return String.Empty;
                }
            }
            Trace.TraceError(String.Format("没有找到封面文件 {0}", album.CoverID));
            return String.Empty;
        }

        public void AttachCover(Album album, String songPath)
        {
            FileInfo info = GetFile(album);
            if (info != null)
            {
                using (FileStream objFileStream = new FileStream(info.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                {
                    UltraID3 id3 = new UltraID3();
                    id3.Read(songPath);
                    ID3FrameCollection id3FrameCollection = id3.ID3v2Tag.Frames.GetFrames(CommonMultipleInstanceID3v2FrameTypes.Picture);
                    if (id3FrameCollection.Count > 0)
                    {
                        #region Remove All Old Artwork
                        for (int i = 0; i < id3FrameCollection.Count; i++)
                        {
                            ID3v2PictureFrame ra = (ID3v2PictureFrame)id3FrameCollection[0];
                            try
                            {
                                id3.ID3v2Tag.Frames.Remove(CommonID3v2FrameTypes.Picture);
                            }
                            catch { }
                        }
                        id3FrameCollection.Clear();
                        id3.Write();
                        id3.Read(songPath);
                        #endregion Remove All Old Artwork
                    }
                    ID3v2PictureFrame AlbumArt = new ID3v23PictureFrame((System.Drawing.Bitmap)System.Drawing.Bitmap.FromFile(info.FullName), PictureTypes.CoverFront, "Attached picture", TextEncodingTypes.ISO88591);
                    id3.ID3v2Tag.Frames.Add(AlbumArt);
                    id3.Write();
                }
            }
        }

        private DirectoryInfo GetDir(String path,DirOptions dirOptions,Album album)
        {
            DirectoryInfo dir = Directory.CreateDirectory(path);
            if ((dirOptions & DirOptions.WithArtists) == DirOptions.WithArtists && album != null)
            {
                String subDirName = BuildFileableName(album.ArtistString);
                dir = dir.CreateSubdirectory(subDirName);
                if ((dirOptions & DirOptions.WithAlbum) == DirOptions.WithAlbum)
                {
                    String subAlbumDirName = BuildFileableName(album.Name);
                    dir = dir.CreateSubdirectory(subAlbumDirName);
                }
            }
            return dir;
        }

        [DllImport("winmm.dll", CharSet = CharSet.Auto)]
        public static extern int mciSendString(string m_strCmd, StringBuilder m_strReceive, int m_v1, int m_v2);
        [DllImport("Kernel32", CharSet = CharSet.Auto)]
        static extern Int32 GetShortPathName(String path, StringBuilder shortPath, Int32 shortPathLength);

        private bool CheckFull(FileInfo info)
        {
            //long length = info.Length;

            //StringBuilder shortpath = new StringBuilder(1024);
            //GetShortPathName(info.FullName, shortpath, shortpath.Capacity);
            //String shortName = shortpath.ToString(); 
            //StringBuilder buf = new StringBuilder(255);
            //mciSendString("open " + shortName + " alias song", null, 0, 0);
            //mciSendString(String.Format("status {0} length", shortName), buf, buf.Capacity, 0);
            //TimeSpan ts = new TimeSpan(0, 0, 0, 0, (int)Convert.ToDouble(buf.ToString().Trim()));
            return true;
        }

        public const String TitleMark = "#song";
        public const String ArtistMark = "#artists";
        public const String AlbumMark = "#album";
        private string GetName(string nameFormate, Song song)
        {
            String name = nameFormate.Replace(TitleMark, song.Title).Replace(AlbumMark, song.Album.Name).Replace(ArtistMark, song.Album.ArtistString);
            return BuildFileableName(name);
        }

        private string BuildFileableName(string name)
        {
            name = name.Replace('/', '+');
            name = name.Replace('\"', '\'');
            name = name.Replace("*", "");
            name = name.Replace("?", "？");
            name = name.Replace("<", "《");
            name = name.Replace(">", "》");
            name = name.Replace("|", " ");
            return name.Trim();
        }
    }
}
